package org.example;
import com.jsyn.JSyn;
import com.jsyn.Synthesizer;
import com.jsyn.unitgen.LineOut;
import com.jsyn.unitgen.SineOscillator;

import java.util.Random;

import java.util.ArrayList;
import java.util.List;

public class Main {
    public static void playFrequencies(double frequency1, double frequency2, int durationInMilliseconds) {
        // 创建合成器上下文
        Synthesizer synth = JSyn.createSynthesizer();

        // 启动合成器，使用默认立体声输出，采样率为 44100 Hz
        synth.start();

        // 创建两个振荡器
        SineOscillator oscillator1 = new SineOscillator();
        SineOscillator oscillator2 = new SineOscillator();
        synth.add(oscillator1);
        synth.add(oscillator2);

        // 添加立体声输出单元
        LineOut lineOut = new LineOut();
        synth.add(lineOut);

        // 将振荡器连接到输出的两个通道
        oscillator1.output.connect(0, lineOut.input, 0);
        oscillator1.output.connect(0, lineOut.input, 1);
        oscillator2.output.connect(0, lineOut.input, 0);
        oscillator2.output.connect(0, lineOut.input, 1);

        // 设置频率和幅度
        oscillator1.frequency.set(frequency1);
        oscillator1.amplitude.set(0.6);
        oscillator2.frequency.set(frequency2);
        oscillator2.amplitude.set(0.6);

        // 启动 LineOut
        lineOut.start();

        // 播放指定时间的声音
        try {
            double startTime = synth.getCurrentTime();
            synth.sleepUntil(startTime + durationInMilliseconds / 1000.0);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        // 停止合成器
        synth.stop();
    }

    public static double[] generateTone(double frequency, double duration, int sampleRate) {
        int nSamples = (int) (sampleRate * duration);
        double[] tone = new double[nSamples];

        for (int i = 0; i < nSamples; i++) {
            double t = (double) i / sampleRate;
            tone[i] = 0.5 * Math.sin(2 * Math.PI * frequency * t);
        }

        return tone;
    }

    /**
     * 播放指定频率和振幅的声音，持续特定的时间。
     *
     * @param frequency 频率，以赫兹为单位，表示声音的高低。
     * @param amplitude 振幅，表示声音的强度或音量。
     * @param durationInMilliseconds 持续时间，以毫秒为单位，表示声音播放的长度。
     */
    public static void playFrequency(double frequency, double amplitude, int durationInMilliseconds) {
        // 方法实现
        // 创建合成器上下文
        System.out.println(frequency);
        Synthesizer synth = JSyn.createSynthesizer();

        // 启动合成器，使用默认立体声输出，采样率为 44100 Hz
        synth.start();

        // 创建振荡器
        SineOscillator oscillator = new SineOscillator();
        synth.add(oscillator);

        // 添加立体声输出单元
        LineOut lineOut = new LineOut();
        synth.add(lineOut);

        // 将振荡器连接到输出的两个通道
        oscillator.output.connect(0, lineOut.input, 0);
        oscillator.output.connect(0, lineOut.input, 1);

        // 设置频率和幅度
        oscillator.frequency.set(frequency);
        oscillator.amplitude.set(amplitude);

        // 启动 LineOut
        lineOut.start();

        // 播放指定时间的声音
        try {
            double startTime = synth.getCurrentTime();
            synth.sleepUntil(startTime + durationInMilliseconds / 1000.0);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        // 停止合成器
        synth.stop();
    }

    public static void song1(){
        playFrequency(200.0,  0.4,1000);
        playFrequency(200.0,  0.4,1000);
        playFrequency(300.0,  0.4,1000);
        playFrequency(300.0,  0.4,1000);
        playFrequency(337.5,  0.4,1000);
        playFrequency(337.5,  0.4,1000);
        playFrequency(300.0,  0.4,1000);
        playFrequency(266.67, 0.4,1000);
        playFrequency(266.67, 0.4,1000);
        playFrequency(253.125,0.4,1000);
        playFrequency(253.125,0.4,1000);
        playFrequency(225.0,  0.4,1000);
        playFrequency(225.0,  0.4,1000);
        playFrequency(200.0,  0.4,1000);
    }


    public static void song2(){
        playFrequency(350,0.6,1000);
        playFrequency(350,0.6,1000);
        playFrequency(525,0.6,1000);
        playFrequency(525,0.6,1000);
        playFrequency(583,0.6,1000);
        playFrequency(583,0.6,1000);
        playFrequency(525,0.6,1000);
        playFrequency(466,0.6, 1000);
        playFrequency(466,0.6, 1000);
        playFrequency(437,0.6, 1000);
        playFrequency(437,0.6, 1000);
        playFrequency(393,0.6,1000);
        playFrequency(393,0.6,1000);
        playFrequency(350,0.6,1000);
    }

    public static void song3(){
        Random random = new Random();
        double x = 100 + (600 - 100) * random.nextDouble(); // 生成100到300之间的随机数

        playFrequency((double)1 * x,    0.4, 1000);
        playFrequency((double)1 * x,    0.4,1000);
        playFrequency((double) 3 /2 * x,0.4,1000);
        playFrequency((double) 3 /2 * x,0.4,1000);
        playFrequency((double) 27/16 * x,0.4,1000);
        playFrequency((double) 27/16 * x,0.4,1000);
        playFrequency((double) 3/2 * x, 0.4,  1000);
        playFrequency((double) 4/3 * x, 0.4, 1000);
        playFrequency((double) 4/3 * x, 0.4, 1000);
        playFrequency((double) 81/64 * x, 0.4,1000);
        playFrequency((double) 81/64 * x, 0.4,1000);
        playFrequency((double) 9/8 * x,0.4,   1000);
        playFrequency((double) 9/8 * x,0.4,1000);
        playFrequency((double)1 * x,0.4,1000);
    }
//
    public static void song4(){
        double x = 200;
        playFrequencies((double)1 * x,(double)4/3 * x,1000);
        playFrequencies((double)1 * x,(double)2/1 * x,1000);
        playFrequencies((double)1 * x,(double) 3 /2 * x,1000);
    }
//
    public static void song5(){
        double x = 200;
        playFrequencies((double)1 * x,(double)21/20 * x,1000);
    }
//
    public static void song6(){
        double x = 200;
        playFrequency((double)1* x,       0.4,1000);
        playFrequency((double)9/8* x,     0.4, 1000);
        playFrequency((double)81/64* x,   0.4,  1000);
        playFrequency((double)4/3* x,     0.4,1000);
        playFrequency((double)3/2* x,     0.4, 1000);
        playFrequency((double)27/16* x,   0.4,   1000);
        playFrequency((double)243/128* x, 0.4,      1000);
        playFrequency((double)2* x,       0.4,     1000);
    }

    public static List<Double> generateTwelveToneEqualTemperament(double baseFrequency,int step) {
        List<Double> frequencies = new ArrayList<>();
        double ratio = Math.pow(2, 1.0 / 12.0); // 12平均律的频率比
        for (int i = 0; i < step; i++) {
            double frequency = baseFrequency * Math.pow(ratio, i);
            frequencies.add(frequency);
        }
        return frequencies;
    }



//    public static void playMajorScale(double baseFrequency, int duration) {
//        int[] majorScaleSteps = {0, 2, 4, 5, 7, 9, 11, 12}; // C大调音阶的半音位置
//        for (int step : majorScaleSteps) {
//            double frequency = baseFrequency * Math.pow(2, step / 12.0);
//            playFrequency(frequency, duration);
//        }
//    }




    public static void main(String[] args) {
        System.out.println("Hello world!");
        song1();
//        song2();
//        song3();
//        song4();
//        song5();
//        song6();

//        playMajorScale(200,1000);
    }
}